#ifndef CKDOP_H
#define CKDOP_H
#include "..//Math/CommonMath.h"
#include "..//Math//CommonStruct.h"
#include <vector>
#include "TypeDef.h"

struct KDNodePair
{
	float			HitTime;
	int				NodeIndex;
	_HOST_DEVICE_ KDNodePair()
	{
		HitTime = FLT_MAX;
		NodeIndex = 0;
	}

	_HOST_DEVICE_ KDNodePair(const KDNodePair& Other)
	{
		HitTime = Other.HitTime;
		NodeIndex = Other.NodeIndex;
	}
};

#define MaxGPUStackCount 32

template<class T>
struct CGPUStack
{
	T			StackElement[MaxGPUStackCount];
	int			CurIndex;

	_HOST_DEVICE_ CGPUStack()
	{
		CurIndex = 0;
	}

	_HOST_DEVICE_ bool IsEmpty()
	{
		return CurIndex<=0;
	}

	_HOST_DEVICE_ T GetTop()
	{
		return StackElement[CurIndex];
	}

	_HOST_DEVICE_ T PopTop()
	{
		return StackElement[--CurIndex];
	}

	_HOST_DEVICE_ void PushElement(T NewElement)
	{
		StackElement[CurIndex++] = NewElement;
	}

	_HOST_DEVICE_ void Clear()
	{
		CurIndex = 0;
	}
};

class CKDop
{
public:
	//TextureSize
	Tuple2i					TextureSize;
	
	int						iStartVertexIndex;
	//0 1 2 3 4 5....triangle index
	int*					pVertexIndexBuffer;

	//Vertex buffer count and buffer
	int						VertexCount;
	CVertex*				pVertexBuffer;

	//triangle vertex index count and index
	int						VertexIndexCount;
	int*					pTriangleIndex;

	//triangle centers
	Tuple3f*				pTriangleCenter;
	
	//kdtree node 
	std::vector<CKDopNode*>	KDopNodes;
	//int*					pKDopNodeTriangleIndex;
	int*					pd_KDopNodeTriangleIndex;
	int						KDopNodeCount;
	CKDopNode*				ph_KDopNode;
	CKDopNode*				pd_KDopNode;

	//restore device rescource
	int*					d_TriangleIndex;
	CVertex*				d_TriangleVertex;
	RasterBufferElement*	d_TriangleUVInfo;
	unsigned char*			d_RasterRes;

	void					CalcTrianglesCenter();

	void					BuildKDopTree();

	void					BeginBuild();
	void					EndBuild();
	void					BuildKDop();

	bool					LineCheck(Tuple3f& Start, Tuple3f& Direction, Tuple3f& UVT);

	void					ReleaseRes();

	void					Raster();

	void					PrepareDeviceData();

	void					ProcessLighting();
public:
	CKDop(void);
	~CKDop(void);
};

_DEVICE_ONLY_ int SceneLineCheck(Tuple3f& Start
								, Tuple3f& Dir	
								, Tuple3f& UVT
								, CVertex* pVertexBuffer
								//, int* pVertexIndexBuffer
								//, int* pTriangleIndexBuffer
								, CKDopNode* pKDTreeRoot
								, CGPUStack<KDNodePair>& LocalStack);


_GLOBAL_ void SceneProcessLighting( RasterBufferElement* pRaseter
								, CVertex*	pTriangleVertex
								//, int* pVertexIndexBuffer
								//, int* pTriangleIndexBuffer
								, CKDopNode* pKDTreeRoot
								, unsigned char* LightMap
								, int* GlobalConstantData
								, Tuple2i LightMapSize
								, int ThreadsCount);

_GLOBAL_ void SceneProcessIndirectionalLighting( RasterBufferElement* pRaseter
								   , CVertex*	pTriangleVertex
								 //  , int* pVertexIndexBuffer
								  // , int* pTriangleIndexBuffer
								   , CKDopNode* pKDTreeRoot
								   , unsigned char* LightMap
								   , int* GlobalConstantData
								   , Tuple2i LightMapSize
								   , int ThreadsCount);

#endif
